package net.unix8.thread;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import org.json.JSONException;
import org.json.JSONObject;

import com.demo.common.model.WaveData;
import com.demo.common.model.WaveStation;
import com.jfinal.kit.PathKit;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import net.unix8.bean.DataIndex;
import net.unix8.bean.GetDataBean;
import net.unix8.bean.WaveDataIndex;
import net.unix8.bean.WaveDataNoSql;
import net.unix8.bean.WaveStationNoSql;
import net.unix8.constant.ConstantsValue;
import net.unix8.share.NetworkShare;
import net.unix8.tool.Tools;
public class GetTimeData extends Thread{

	private ChannelId channel;
	private int id;
	private String host;
	private long time;
	private long interval;
	private boolean useSql;
	public GetTimeData() {
		super();
	}
	
	public GetTimeData(ChannelId channel,int id,String host, long time, long interval, boolean useSql) {
		super();
		this.host = host;
		this.time = time;
		this.interval = interval;
		this.channel = channel;
		this.id = id;
		this.useSql = useSql;
	}
	//合并后的三通道数据
	byte [][]mergeData = null;
	//文件记录信息
	WaveDataIndex fileTimeRecord;// = new WaveDataIndex();
	/**
	 * 根据秒+微秒数查询记录文件
	 * @param sTime  秒
	 * @param usTime 微秒
	 * @return 返回数据索引，开始时间转换成微秒，结束时间转换成微秒，以及文件名
	 */
	public DataIndex queryFileNameNoSQL(long sTime, long usTime, boolean dir){
		//System.out.println("无站SQL");
		WaveStationNoSql waveStation = null;
		Vector<WaveStationNoSql> stations = NetworkShare.stations;
		for (WaveStationNoSql x : stations){
			if( host.equals(x.ip)){
				waveStation = x;
				break;
			}	
		}
		if(waveStation == null) return null;	
		
/*		System.out.println("有站"+waveStation.id + "   " + waveStation.ip);
		for (WaveDataNoSql x : NetworkShare.datas){
			System.out.println("数据"+sTime+" ->  "+x.sid + "   " + x.stimeS+"   "+x.etimeS);
		}
		*/
		
		int s_ID = waveStation.id;
		//System.out.println(s_ID + "   " + sTime+"   "+sTime);
		List<WaveDataNoSql> waveDataNoSQL = new ArrayList<WaveDataNoSql>();
		for (WaveDataNoSql x : NetworkShare.datas){
			if((s_ID == x.sid) && (x.stimeS <= sTime) && (x.etimeS >= sTime)){				
				waveDataNoSQL.add(x);
			}	
		}
		
		//ArrayList<WaveDataIndex> waveDatas = new ArrayList<WaveDataIndex>();
		long t0 = sTime * 1000000 + usTime;
		for(WaveDataNoSql element: waveDataNoSQL)
		{
			//WaveDataIndex waveDataIndex = new WaveDataIndex(element.getLong("d_start_s"), 
			//		element.getLong("d_end_s"), element.getLong("d_start_us"), element.getLong("d_end_us"),element.getStr("url"));
			long t1 = element.stimeS * 1000000l + element.stimeUS;
			long t2 = element.etimeS * 1000000l + element.etimeUS;
			if(dir == true){
				if((t1 < t0) && (t2 >= t0)){
					String mPathString = PathKit.getWebRootPath() + "/mdata/" + host+"/";
					DataIndex dataIndex = new DataIndex(mPathString + element.file, t1, t2);
					//System.out.println(dataIndex);
					return dataIndex;
				}
			}else{
				if((t1 <= t0) && (t2 > t0)){
					String mPathString = PathKit.getWebRootPath() + "/mdata/" + host+"/";
					DataIndex dataIndex = new DataIndex(mPathString + element.file, t1, t2);
					//System.out.println(dataIndex);
					return dataIndex;
				}
			}
		}
		return null;
	}

	/**
	 * 根据秒+微秒数查询记录文件
	 * @param sTime  秒
	 * @param usTime 微秒
	 * @return 返回数据索引，开始时间转换成微秒，结束时间转换成微秒，以及文件名
	 */
	public DataIndex queryFileNameSQL(long sTime, long usTime, boolean dir){
		//System.out.println("有站sql");
		WaveStation waveStation = WaveStation.dao.findFirst("select * from wave_station where s_ip = ?", host);
		if(waveStation == null) return null;		
		int s_ID = waveStation.getId();
		//System.out.println(s_ID + "   " + sTime+"   "+sTime);

		List<WaveData> waveDataSQL = WaveData.dao.find("select * from wave_data where s_ID = ? and d_start_s <= ? and d_end_s >= ?",s_ID, sTime, sTime);//Time	
		//ArrayList<WaveDataIndex> waveDatas = new ArrayList<WaveDataIndex>();
		long t0 = sTime * 1000000 + usTime;
		for(WaveData element: waveDataSQL)
		{
			//WaveDataIndex waveDataIndex = new WaveDataIndex(element.getLong("d_start_s"), 
			//		element.getLong("d_end_s"), element.getLong("d_start_us"), element.getLong("d_end_us"),element.getStr("url"));
			long t1 = element.getLong("d_start_s") * 1000000l + element.getLong("d_start_us");
			long t2 = element.getLong("d_end_s") * 1000000l + element.getLong("d_end_us");
			if(dir == true){
				if((t1 < t0) && (t2 >= t0)){
					String mPathString = PathKit.getWebRootPath() + "/mdata/" + host+"/";
					DataIndex dataIndex = new DataIndex(mPathString + element.getStr("d_data_url"), t1, t2);
					//System.out.println(dataIndex);
					return dataIndex;
				}
			}else{
				if((t1 <= t0) && (t2 > t0)){
					String mPathString = PathKit.getWebRootPath() + "/mdata/" + host+"/";
					DataIndex dataIndex = new DataIndex(mPathString + element.getStr("d_data_url"), t1, t2);
					//System.out.println(dataIndex);
					return dataIndex;
				}
			}
		}
		return null;
	}

	/**
	 * 根据微秒查询记录文件，该微秒指的是（秒*1000000 + 微秒）
	 * @param usTime
	 * @return
	 */
	public DataIndex queryFileName(long usTime, boolean dir){
		long i = (long)(usTime / 1000000l);
		long f = (long)(usTime % 1000000l);
		if(!useSql)
			return queryFileNameNoSQL(i, f, dir);
		else
			return queryFileNameSQL(i, f, dir);
	}

	/**
	 * 查找某个微秒时间点，向前间隔为usInterval的数据文件
	 * @param usTime
	 * @param usInterval
	 * 为了避免无休止的调用，当时间间隔小于阈值不再处理
	 */
	private void doWorkInsert(long usTime, long usInterval){//byte[]+null?
		if(usInterval < ConstantsValue.TOLERATE_ERROR) return;
		//根据时间从数据库找定位第一个文件,文件名为file1
		DataIndex dataIndex = queryFileName(usTime, true);
		if(dataIndex == null) return;

		//System.out.println("FILE:"+"  "+dataIndex);
		//start为该文件开始时间，end为该文件的结束时间(都转换成微秒)
		long start = dataIndex.start, end = dataIndex.end;
		String file = dataIndex.name;

		if(usTime < start || usTime > end)	
			throw new IllegalArgumentException("该文件的开始时间比定位到的时间还晚");   
		if(usTime - start >= usInterval){
			//System.out.println("Insert[1]: "+(usTime - usInterval)+" -> "+usTime);
			byte [][] tData = readFile(file,usTime - usInterval,usTime);
			if(tData == null) return;

			mergeData = Tools.ByteArrayInsert(mergeData, tData);//是否会覆盖，待测试
			fileTimeRecord.setFileTimeStartRecord(usTime - usInterval);
		}else
		{
			//System.out.println("Insert[2]: "+start+" -> "+usTime);
			byte [][] tData = readFile(file, start, usTime);
			if(tData == null) return;

			mergeData = Tools.ByteArrayInsert(mergeData, tData);//是否会覆盖，待测试
			fileTimeRecord.setFileTimeStartRecord(start);

			doWorkInsert(start, usInterval - usTime + start);
			/*找其他文件并递归添加*/		
		}
	}

	private void doWorkAppend(long usTime, long usInterval){//byte[]+null?
		if(usInterval < ConstantsValue.TOLERATE_ERROR) return;
		//根据时间从数据库找定位第一个文件,文件名为file1
		DataIndex dataIndex = queryFileName(usTime,false);
		if(dataIndex == null) return;

		//start为该文件开始时间，end为该文件的结束时间(都转换成微秒)
		long start = dataIndex.start, end = dataIndex.end;
		String file = dataIndex.name;

		if(usTime > end)
			throw new IllegalArgumentException("该文件的开始时间比定位到的时间还晚");   
		if(end - usTime >= usInterval){
			//System.out.println("Append[1]: "+usTime+" -> "+(usTime + usInterval));
			byte [][] tData = readFile(file,usTime,usTime + usInterval);
			if(tData == null) return;
			mergeData = Tools.ByteArrayAppend(mergeData, tData);//是否会覆盖，待测试
			fileTimeRecord.setFileTimeEndRecord(usTime + usInterval);		
		}else
		{
			//System.out.println("Append[2]: "+usTime+" -> "+end);
			byte [][] tData = readFile(file, usTime, end);
			if(tData == null) return;

			mergeData = Tools.ByteArrayAppend(mergeData, tData);//是否会覆盖，待测试
			fileTimeRecord.setFileTimeEndRecord(end);		
			doWorkAppend(end, usInterval - end + usTime);
			/*找其他文件并递归添加*/		
		}
	}


	public String genResuleFile(long time, long interval) throws IOException{
		//System.out.println("-------------------------MTIME---------------------------");
		doWorkInsert(time /* 1000000*/, interval * 500000l);
		//System.out.println("----------------------------------------------------");
		doWorkAppend(time  /* 1000000*/, interval * 500000l);
		//System.out.println("----------------------------------------------------");
		fileTimeRecord.calPoints();
		//System.out.println(fileTimeRecord);
		if(mergeData != null  && fileTimeRecord.points != 0){
			
			byte []headFirst =  Tools.readFiletoNByteArray(fileTimeRecord.file, 0, ConstantsValue.HEAD_LENGTH);	
			String headFistStrinigF = new String(headFirst,0,80,"ISO-8859-1");
			String headFistStrinigB = new String(headFirst,80,48,"ISO-8859-1");
			
			String[] arrsFront=null; 
			arrsFront=headFistStrinigF.split(":");
			if(arrsFront.length < 3) return null;
			arrsFront[1] = String.valueOf(fileTimeRecord.points);
			arrsFront[2] = String.valueOf(fileTimeRecord.rate);
			
			String[] arrsBack=headFistStrinigB.split(":");
			if(arrsFront.length < 2) return null;			
			arrsBack[0] = String.valueOf(fileTimeRecord.stimeS) + "." + String.valueOf(fileTimeRecord.stimeUS);
			arrsBack[1] = String.valueOf(fileTimeRecord.etimeS) + "." + String.valueOf(fileTimeRecord.etimeUS);
			
			byte []headFirstNew = new byte[128]; 
			//修改结束时间，重新生成头部		
			StringBuffer sbFront = new StringBuffer();
			for(int ii = 0; ii < arrsFront.length-1; ii++){
				sbFront. append(arrsFront[ii]+":");
			}
			sbFront. append(arrsFront[arrsFront.length-1]);
			String sFront = sbFront.toString();
			headFirst = sFront.getBytes("ISO-8859-1");
			System.arraycopy(headFirst, 0, headFirstNew, 0, (headFirst.length > 80 ? 80:headFirst.length));
			
			StringBuffer sbBack = new StringBuffer();
			for(int ii = 0; ii < arrsBack.length-1; ii++){
				sbBack. append(arrsBack[ii]+":");
			}
			sbBack. append(arrsBack[arrsBack.length-1]);
			String sBack = sbBack.toString();
			headFirst = sBack.getBytes("ISO-8859-1");		
			System.arraycopy(headFirst, 0, headFirstNew, 80, (headFirst.length > 48 ? 48:headFirst.length));
			
			String pathString = PathKit.getWebRootPath() + "/tmp/" ;
			File fileSdata =new File(pathString);    
			if  (!fileSdata .exists()  && !fileSdata .isDirectory()){fileSdata .mkdir();} 
			String[] files = fileSdata.list();
			int len = files.length;
			SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置日期格式
			String date = df.format(new Date());
			host = host.replace('.', '_');
			if(len > 300) {
			for(int i = 0; i < len - 20; ++i) {				
					Tools.deleteFile(pathString+files[i]);
				}
			}
			
			String t = host+"-"+date;
			
			pathString = pathString + t;
			fileSdata =new File(pathString);    
			if(!fileSdata.exists())
				fileSdata.createNewFile();
			Tools.writeByteNToFile(pathString, 0, ConstantsValue.HEAD_LENGTH, headFirstNew);
			Tools.writeByteNToFile(pathString, ConstantsValue.HEAD_LENGTH, fileTimeRecord.points * 4, mergeData);
			return t;
		}else
			return null;

	}

	@Override
	public void run() {
		GetDataBean bean = null;
		while(true) {
			try {
				 bean = NetworkShare.getDataQueue.take();
			} catch (InterruptedException e1) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					continue;
				}
			}
			if(bean == null) continue;
			mergeData = null;
			fileTimeRecord = null;
			fileTimeRecord = new WaveDataIndex();
			this.host = bean.host;
			this.time = bean.time;
			this.interval = bean.interval;
			this.channel = bean.channel;
			this.id = bean.id;
			this.useSql = bean.useSql;
			
			//System.out.println("-MTIME-"+this.time+"  "+ this.interval + " "+this.id );
			Boolean status = false;
			String fileName = null;
			try {
				fileName =  genResuleFile(time,interval);
				if(fileName != null)status = true;
			} catch (Exception e) {	
				fileName = null;
				e.printStackTrace();
			}

			JSONObject studentJSONObject = new JSONObject();  
			try {  
				studentJSONObject.put("host", host);
				studentJSONObject.put("id", 0);  
				studentJSONObject.put("cmd", "data"); 
				studentJSONObject.put("status", status);  
				if((fileName == null) || (status ==false)){
					fileName = "Can not find the file";
				}
				studentJSONObject.put("data", fileName);  
			} catch (JSONException e) {  
				e.printStackTrace();  
			}  

			Channel remoteChannel = NetworkShare.clientGroup.find(channel);
			if(remoteChannel != null){
				final ByteBuf firstMessage;
				firstMessage = Unpooled.buffer(100);
				firstMessage.writeCharSequence(studentJSONObject.toString(), Charset.forName("UTF-8"));
				remoteChannel.writeAndFlush(firstMessage);
			}
		}
	}

	/*
	 * start为开始的时间,end为结束的时间,微秒为单位
	 */
	public  byte [][] readFile(String file, long start, long end) {   
		try {
			byte []headFirst =  Tools.readFiletoNByteArray(file, 0, ConstantsValue.HEAD_LENGTH);	
			String headFistStrinigF = new String(headFirst,0,40,"ISO-8859-1");
			String headFistStrinigB = new String(headFirst,80,48,"ISO-8859-1");
			String[] arrsFirst=null; 
			arrsFirst=headFistStrinigF.split(":");
			if(arrsFirst.length < 3) return null;
			//long t1First, t2First, t11First,t22First,pointsFirst,rateFirst;
			long t1, t2, t11,t22,points,rate;
			points = Long.parseLong(arrsFirst[1].trim());//点数
			rate = Long.parseLong(arrsFirst[2].trim());//采样率
			
			arrsFirst=headFistStrinigB.split(":");
			String[] arrs1First=null;
			arrs1First = arrsFirst[0].trim().split("\\.");
			t1 = Long.parseLong(arrs1First[0].trim());t2 =  Long.parseLong(arrs1First[1].trim());
			arrs1First = arrsFirst[1].split("\\.");
			t11 = Long.parseLong(arrs1First[0].trim());t22 =  Long.parseLong(arrs1First[1].trim());
						
			/*这两个字段，借用了该过程中任意一个文件的头部信息*/
			fileTimeRecord.setRate(rate);
			fileTimeRecord.setFile(file);
			long fs = t1 * 1000000l + t2;
			long fe = t11 * 1000000l + t22;
			if(start < fs || start  > fe ||end < fs || end > fe || start > end ){
				return null;
			}

			double k = (double)(fe - fs) / (double) points;//每个点所占微秒数
			//System.out.println("K: " + k + "   " + (long)(k*points)+ " "+(fe - fs) );
			
			long p = (long) ((double)(start - fs) / (double)k) ;
			long step = (long) ((double)(end - start) / (double)k) ;
			fileTimeRecord.addPoint(step);
			//System.out.println("SIZE: " + p+ "  " + step + "  " + points);
			
			byte [][]data = new byte[3][];
		
			long e1 = ConstantsValue.HEAD_LENGTH + points * 4l;//第1个通道的截止字节
			long e2 = ConstantsValue.HEAD_LENGTH +  points * 4l * 2l;//第2个通道的截止字节
			long e3 = ConstantsValue.HEAD_LENGTH +  points * 4l * 3l;//第3个通道的截止字节
			
			long s1 = ConstantsValue.HEAD_LENGTH + p * 4l; 
			long s2 = ConstantsValue.HEAD_LENGTH + points * 4l + p * 4l;
			long s3 = ConstantsValue.HEAD_LENGTH + points * 4l * 2l + p * 4l;
			//System.out.println("<----------1---------->" +step+ "  " + fs + "  " + fe);
			//System.out.println("E1: " +  s1+" ->  " +(s1+step* 4l));
			//System.out.println("E2: " +  s2+" -> " +(s2+step* 4l));
			//System.out.println("E3: " +  s3+" -> " +(s3+step* 4l));				
			data[0] = Tools.readFiletoNByteArray(file,s1 ,step * 4l);//从start开始读取数据x
			data[1] = Tools.readFiletoNByteArray(file,s2 ,step * 4l);//从start开始读取数据y
			data[2] = Tools.readFiletoNByteArray(file,s3 ,step * 4l);//从start开始读取数据z
			//System.out.println("<---------2----------->" );

			return data;

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}  
}
